package com.pragmatic.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 发送http请求
 *
 * @author wangdong
 * @since 2025/4/22 11:24
 */
@Slf4j
public class HttpClientUtil {

  // 默认字符集
  private static final String DEFAULT_ENCODE = "UTF-8";
  // 请求头
  private static final String HTTP_HEADER_REQUEST_ID = "X-RequestId";

  public static String sendPostJsonStr(String url, String jsonStr, int timeOut) {
    return sendPostJsonBase(url, jsonStr, DEFAULT_ENCODE, new HashMap<String, String>(), timeOut);
  }

  /**
   * httpPost 请求
   *
   * @param url 请求路径
   * @param jsonStr 参数json
   * @param charset 字符集
   * @param headers 请求头对象
   * @param timeOut 超时时间
   * @return 响应结果
   */
  public static String sendPostJsonBase(
      String url, String jsonStr, String charset, Map<String, String> headers, int timeOut) {
    HttpPost post = new HttpPost(url);
    if (headers != null && headers.size() > 0) {
      for (Map.Entry<String, String> entry : headers.entrySet()) {
        post.setHeader(entry.getKey(), entry.getValue());
      }
    }
    StringEntity entity = new StringEntity(jsonStr, charset);
    entity.setContentEncoding(charset);
    entity.setContentType("application/json;charset=" + charset);
    post.setEntity(entity);
    return execute(post, timeOut);
  }

  /**
   * 发送httpPost请求
   *
   * @param requestBase post对象
   * @param timeOut 超时时间
   * @return 响应结果
   */
  private static String execute(HttpRequestBase requestBase, int timeOut) {
    StringBuilder sb = new StringBuilder();
    BufferedReader reader = null;
    CloseableHttpResponse response = null;
    CloseableHttpClient httpClient = getClient(timeOut);
    try {
      String uuid = UUID.randomUUID().toString();
      requestBase.setHeader(HTTP_HEADER_REQUEST_ID, uuid);
      // 执行
      long start = System.currentTimeMillis();
      response = httpClient.execute(requestBase);
      log.info(
          "请求url: {} , 耗时: {} ",
          requestBase.getURI().toString(),
          (System.currentTimeMillis() - start));
      HttpEntity entity = response.getEntity();
      reader = new BufferedReader(new InputStreamReader(entity.getContent(), DEFAULT_ENCODE));
      String line = reader.readLine();
      while (line != null) {
        sb.append(line);
        line = reader.readLine();
      }
      EntityUtils.consume(entity);

    } catch (Exception e) {
      log.error("远程调用异常", e);
      throw new RuntimeException("远程调用异常", e);
    } finally {
      try {
        if (reader != null) {
          reader.close();
        }
        if (response != null) {
          response.close();
        }
        httpClient.close();
      } catch (IOException e) {
        log.error("远程调用异常", e);
      }
    }
    return sb.toString();
  }

  /**
   * 创建http连接
   *
   * @param timeOut 超时时间
   * @return CloseableHttpClient
   */
  public static CloseableHttpClient getClient(int timeOut) {
    RequestConfig requestConfig =
        RequestConfig.custom()
            .setConnectionRequestTimeout(timeOut)
            .setConnectTimeout(timeOut)
            .setSocketTimeout(timeOut)
            .build();

    SSLContext sslContext = buildIgnoreContext();
    // 注册
    Registry<ConnectionSocketFactory> registry =
        RegistryBuilder.<ConnectionSocketFactory>create()
            .register("http", PlainConnectionSocketFactory.INSTANCE)
            .register(
                "https", new SSLConnectionSocketFactory(sslContext, new AllowAllHostnameVerifier()))
            .build();
    PoolingHttpClientConnectionManager connManager =
        new PoolingHttpClientConnectionManager(registry);
    return HttpClients.custom()
        .setConnectionManager(connManager)
        .setDefaultRequestConfig(requestConfig)
        .build();
  }

  /**
   * 忽略 ssl
   *
   * @return SSLContext
   */
  private static SSLContext buildIgnoreContext() {
    SSLContext sslContext = null;
    try {
      sslContext = SSLContext.getDefault();
      // 实现一个X509TrustManager接口，用于绕过验证，不用修改里面的方法
      X509TrustManager x509TrustManager =
          new X509TrustManager() {
            @Override
            public X509Certificate[] getAcceptedIssuers() {
              return null;
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {}

            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {}
          };
      sslContext.init(null, new TrustManager[] {x509TrustManager}, null);
    } catch (NoSuchAlgorithmException e) {
      log.error(e.getMessage(), e);
    } catch (KeyManagementException e) {
      // if(loger.isDebugEnabled()){
      //    loger.debug(e.getMessage(), e);
      // }
    }

    return sslContext;
  }
}
